package com.quartet.modules.order.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.quartet.annotation.Log;
import com.quartet.api.ApiResult;
import com.quartet.api.MapServerException;
import com.quartet.api.PageResult;
import com.quartet.api.ResultErrorEnum;
import com.quartet.modules.order.dto.MyEmailDto;
import com.quartet.modules.customer.entity.TCustomerInfo;
import com.quartet.modules.customer.service.TCustomerInfoService;
import com.quartet.modules.order.dto.TOrderAddRequestDto;
import com.quartet.modules.order.dto.TOrderRequestDto;
import com.quartet.modules.order.dto.TOrderResponseDto;
import com.quartet.modules.order.entity.TOrder;
import com.quartet.modules.order.service.TOrderService;
import com.quartet.modules.quartz.utils.HttpUtils;
import com.quartet.modules.service.entity.TServiceInfo;
import com.quartet.modules.service.service.TServiceInfoService;
import com.quartet.modules.stock.dao.TTerminalStockDao;
import com.quartet.modules.stock.dto.TTerminalServiceMessageDto;
import com.quartet.modules.stock.entity.TFlowCardStock;
import com.quartet.modules.stock.entity.TTerminalStock;
import com.quartet.modules.stock.service.TFlowCardStockService;
import com.quartet.modules.stock.service.TTerminalStockService;
import com.quartet.modules.system.service.DictDetailServicePs;
import com.quartet.modules.terminal.entity.TRegist;
import com.quartet.modules.terminal.entity.TTerminalInfo;
import com.quartet.modules.terminal.service.TRegistService;
import com.quartet.modules.terminal.service.TTerminalInfoService;
import com.quartet.utils.*;
import com.quartet.utils.constant.MapServerConstant;
import com.quartet.utils.enums.ActiveStatusEnum;
import com.quartet.utils.enums.InventoryStatusEnum;
import com.quartet.utils.enums.OrderStatusEnum;
import com.quartet.utils.enums.ServiceStatusEnum;
import com.quartet.validation.QueryValidation;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 订单表(TOrder)表控制层
 *
 * @author makejava
 * @since 2021-05-04 16:40:24
 */
@RestController
@RequestMapping("tOrder")
@Slf4j
@Api(tags = "业务：订单信息")
public class TOrderController {
    /**
     * 服务对象
     */
    @Resource
    private TOrderService tOrderService;

    @Resource
    private TCustomerInfoService tCustomerInfoService;

    @Resource
    private DictDetailServicePs dictDetailServicePs;
    @Resource
    private TTerminalInfoService tTerminalInfoService;
    @Resource
    private TTerminalStockService tTerminalStockService;
    @Resource
    private TServiceInfoService tServiceInfoService;
    @Resource
    private TRegistService tRegistService;
    @Resource
    private TFlowCardStockService tFlowCardStockService;
    @Resource
    private TTerminalStockDao tTerminalStockDao;
    @Resource
    private AliSmsUtil aliSmsUtil;

    @Resource
    private EmailUtil emailUtil;

    @Value("#{'${orderRemindTimeList}'.split(',')}")
    private List<Integer> orderRemindTimeList;

    @Value("${emailSubject}")
    private String emailSubject;

    @Value("${emailContent}")
    private String emailContent;

    /**
     * 分页查询所有数据
     *
     * @param tOrderRequestDto 查询实体
     * @return 所有数据
     */
    @ApiOperation("分页查询所有订单信息")
    @PostMapping("/query-page")
    public ApiResult<PageResult<TOrderResponseDto>> selectOrderPage(@RequestBody @Validated(QueryValidation.class) TOrderRequestDto tOrderRequestDto) {
        log.info("---------selectOrderPage begin, tCustomerInfoRequestDto is {}----------", tOrderRequestDto);
        IPage<TOrder> page = new Page<>(tOrderRequestDto.getCurrent(), tOrderRequestDto.getLimit());
        QueryWrapper<TOrder> queryWrapper = new QueryWrapper<>();
        if (!ObjectUtils.isEmpty(tOrderRequestDto.getExpireStartTime())) {
            queryWrapper.lambda().ge(TOrder::getExpireTime, tOrderRequestDto.getExpireStartTime());
        }
        if (!ObjectUtils.isEmpty(tOrderRequestDto.getExpireEndTime())) {
            queryWrapper.lambda().le(TOrder::getExpireTime, tOrderRequestDto.getExpireEndTime());
        }

        if (!ObjectUtils.isEmpty(tOrderRequestDto.getOrderName())) {
            queryWrapper.lambda().eq(TOrder::getOrderName, tOrderRequestDto.getOrderName());
        }
        if (!ObjectUtils.isEmpty(tOrderRequestDto.getCustomerCode())) {
            queryWrapper.lambda().eq(TOrder::getCustomerCode, tOrderRequestDto.getCustomerCode());
        }
        if (StringUtils.isNotBlank(tOrderRequestDto.getCustomerName())) {
            List<String> customerCodeList = tCustomerInfoService.list(new QueryWrapper<TCustomerInfo>().lambda()
                    .like(TCustomerInfo::getCustomerName, tOrderRequestDto.getCustomerName())).stream()
                    .map(tCustomerInfo -> tCustomerInfo.getCustomerCode()).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(customerCodeList)) {
                queryWrapper.lambda().in(TOrder::getCustomerCode, customerCodeList);
            } else {
                PageResult<TOrderResponseDto> pageResult = new PageResult();
                pageResult.setData(Collections.emptyList());
                pageResult.setTotal(0L);
                return ApiResult.ok(pageResult);
            }
        }
        if (StringUtils.isNotBlank(tOrderRequestDto.getField())) {
            queryWrapper.orderBy(true, tOrderRequestDto.isAsc(), tOrderRequestDto.getField());
        } else {
            queryWrapper.orderBy(true, tOrderRequestDto.isAsc(), MapServerConstant.CREATE_TIME);
        }
        IPage<TOrder> dbResult = tOrderService.page(page, queryWrapper);
        PageResult<TOrderResponseDto> pageResult = new PageResult();
        List<TOrderResponseDto> tOrderResponseDtoList = dbResult.getRecords().stream().map(tOrder -> {
            TOrderResponseDto tOrderResponseDto = BeanUtil.copyProperties(tOrder, TOrderResponseDto.class);
            QueryWrapper<TCustomerInfo> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.lambda().eq(TCustomerInfo::getCustomerCode, tOrderResponseDto.getCustomerCode());
            TCustomerInfo tCustomerInfo = tCustomerInfoService.getOne(queryWrapper1);
            if (!ObjectUtils.isEmpty(tCustomerInfo)) {
                tOrderResponseDto.setCustomerName(tCustomerInfo.getCustomerName());
            }
            tOrderResponseDto.setApplicationTypeLabel(dictDetailServicePs.getLabelByValueByCode(tOrderResponseDto.getApplicationType()));
            calOrderBalance(tOrderResponseDto);
            QueryWrapper<TTerminalStock> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.lambda().eq(TTerminalStock::getOrderCode, tOrder.getOrderCode());
            List<TTerminalStock> tTerminalStockList = tTerminalStockService.list(queryWrapper2);
            List<String> terminalCodeList = tTerminalStockList.stream().map(tTerminalStock -> tTerminalStock.getTerminalCode()).collect(Collectors.toList());
            tOrderResponseDto.setTerminalCodeList(terminalCodeList);
            return tOrderResponseDto;
        }).collect(Collectors.toList());
        pageResult.setTotal(dbResult.getTotal());
        pageResult.setData(tOrderResponseDtoList);
        log.info("---------selectOrderPage end, data is {}----------", pageResult);
        return ApiResult.ok(pageResult);
    }

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @ApiOperation("通过主键查询单条订单信息")
    @GetMapping("/selectById")
    public ApiResult<TOrderResponseDto> selectById(@RequestParam Integer id) {
        TOrder tOrder = tOrderService.getById(id);
        TOrderResponseDto tOrderResponseDto = BeanUtil.copyProperties(tOrder, TOrderResponseDto.class);
        tOrderResponseDto.setApplicationTypeLabel(dictDetailServicePs.getLabelByValueByCode(tOrderResponseDto.getApplicationType()));
        calOrderBalance(tOrderResponseDto);
        QueryWrapper<TTerminalStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TTerminalStock::getOrderCode, tOrder.getOrderCode());
        List<TTerminalStock> tTerminalStockList = tTerminalStockService.list(queryWrapper);
        List<String> terminalCodeList = tTerminalStockList.stream().map(tTerminalStock -> tTerminalStock.getTerminalCode()).collect(Collectors.toList());
        tOrderResponseDto.setTerminalCodeList(terminalCodeList);
        return ApiResult.ok(tOrderResponseDto);
    }

    /**
     *  计算订单余额
     * @param tOrderResponseDto
     */
    private void calOrderBalance(TOrderResponseDto tOrderResponseDto) {
        //计算订单余额
        LocalDateTime startTime = tOrderResponseDto.getStartTime();
        LocalDateTime expireTime = tOrderResponseDto.getExpireTime();
        BigDecimal totalPaymentPrice = tOrderResponseDto.getTotalPaymentPrice();
        if (expireTime.isBefore(LocalDateTime.now())) {
            tOrderResponseDto.setOrderBalance(new BigDecimal("0"));
        } else {
            long l = startTime.toEpochSecond(ZoneOffset.ofHours(0));
            long l1 = expireTime.toEpochSecond(ZoneOffset.ofHours(0));
            long l2 = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(0));
            BigDecimal divide = totalPaymentPrice.multiply(new BigDecimal(String.valueOf(l1 - l2))).divide(new BigDecimal(String.valueOf(l1 - l)), 2, RoundingMode.HALF_UP);
            tOrderResponseDto.setOrderBalance(divide);
        }
    }

    /**
     * 新增数据
     *
     * @param tOrderAddRequestDto 实体对象
     * @return 新增结果
     */
    @ApiOperation("新增订单信息")
    @PostMapping("/add")
    @Transactional(rollbackFor = Exception.class)
    public ApiResult add(@RequestBody @Validated TOrderAddRequestDto tOrderAddRequestDto) {
        log.info("---------addOrder begin, tOrderAddRequestDto is {}----------", tOrderAddRequestDto);
        //校验是否有当前客户
        List<TCustomerInfo> tCustomerInfoList = tCustomerInfoService.list(new QueryWrapper<TCustomerInfo>().lambda().eq(TCustomerInfo::getCustomerCode, tOrderAddRequestDto.getCustomerCode()));
        if (CollectionUtils.isEmpty(tCustomerInfoList)) {
            throw new MapServerException(ResultErrorEnum.BMKPM001);
        }
        TOrder tOrder = BeanUtil.copyProperties(tOrderAddRequestDto, TOrder.class);
        //根据当前时间和购买周期计算到期时间
        LocalDateTime currentTime = tOrderAddRequestDto.getStartTime();
        Integer usePeriod = tOrderAddRequestDto.getUsePeriod();
        LocalDateTime expireTime = currentTime.plusMonths(usePeriod);
        tOrder.setExpireTime(expireTime);
        //生成订单编码
        String orderCode = RandomUtils.getOrderCode();
        tOrder.setOrderCode(orderCode);
        //默认已支付
        tOrder.setPaymentStatus(2);
        int quantity = tOrderAddRequestDto.getTerminalCodeList().size();
        //根据单价和数量以及周期计算总价
        BigDecimal totalPaymentPrice = tOrderAddRequestDto.getPrice().multiply(new BigDecimal(tOrderAddRequestDto.getUsePeriod()))
                .multiply(new BigDecimal(quantity));
        tOrder.setQuantity(quantity);
        tOrder.setTotalPaymentPrice(totalPaymentPrice);
        tOrder.setOrderKey(RandomUtils.getOrderKey());
        //添加订单信息
        this.tOrderService.save(tOrder);

        //绑定终端给订单
        if (!CollectionUtils.isEmpty(tOrderAddRequestDto.getTerminalCodeList())) {
            UpdateWrapper<TTerminalStock> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().in(TTerminalStock::getTerminalCode, tOrderAddRequestDto.getTerminalCodeList())
                    .set(TTerminalStock::getOrderCode, orderCode)
                    .set(TTerminalStock::getDeliveryTime, LocalDateTime.now())
                    .set(TTerminalStock::getInventoryStatus, InventoryStatusEnum.ALLOCATED.getValue());
            tTerminalStockService.update(updateWrapper);

            updateFlowCardStockStatus(tOrderAddRequestDto.getTerminalCodeList());

            //维护客户的已分配终端数量
            tCustomerInfoService.updateCustomerAssignedTerminalsNum(tOrderAddRequestDto.getCustomerCode(), tOrderAddRequestDto.getTerminalCodeList().size());
            sendMessage(tOrderAddRequestDto.getTerminalCodeList(), tOrder.getCustomerCode());
            //给协议方发送终端权限信息

            List<TTerminalInfo> tTerminalInfoList = tTerminalInfoService.list(new QueryWrapper<TTerminalInfo>().lambda().in(TTerminalInfo::getTerminalCode, tOrderAddRequestDto.getTerminalCodeList()));
            List<TTerminalServiceMessageDto> serviceMessageDtoList = tOrderAddRequestDto.getTerminalCodeList().stream().map(s -> {
                TTerminalServiceMessageDto tTerminalServiceMessageDto = new TTerminalServiceMessageDto();
                String flowCardNumber = tTerminalInfoList.stream().filter(x -> x.getTerminalCode().equals(s)).findAny().map(TTerminalInfo::getFlowCardNumber).orElse("");
                tTerminalServiceMessageDto.setFlowCardNumber(flowCardNumber);
                tTerminalServiceMessageDto.setLocationAuth(false);
                tTerminalServiceMessageDto.setAlarmAuth(false);
                return tTerminalServiceMessageDto;
            }).collect(Collectors.toList());
            log.info("新增订单时推送权限为：{}", serviceMessageDtoList);
            HttpUtils.sendAuthInfo(serviceMessageDtoList);
//            tTerminalStockService.sendTTerminalServiceMessageDto();
        }
        return ApiResult.ok();
    }

    /**
     * 修改设备对应的流量卡状态
     *
     * @param terminalCodeList
     */
    private void updateFlowCardStockStatus(List<String> terminalCodeList) {
        log.info("修改设备对应的流量卡状态为已激活，参数为：{}", terminalCodeList);
        List<TTerminalInfo> tTerminalInfoList = tTerminalInfoService.list(new QueryWrapper<TTerminalInfo>().lambda().in(TTerminalInfo::getTerminalCode, terminalCodeList));
        if (CollectionUtils.isEmpty(tTerminalInfoList)) {
            return;
        }
        List<String> flowCardNumberList = tTerminalInfoList.stream().map(TTerminalInfo::getFlowCardNumber).collect(Collectors.toList());
        UpdateWrapper<TFlowCardStock> updateWrapper1 = new UpdateWrapper<>();
        updateWrapper1.lambda().in(TFlowCardStock::getFlowCardNumber, flowCardNumberList)
                .set(TFlowCardStock::getInventoryStatus, ActiveStatusEnum.ALLOCATED.getValue())
                .set(TFlowCardStock::getDeliveryTime, LocalDateTime.now());
        tFlowCardStockService.update(updateWrapper1);
    }

    /**
     * 发送注册的消息
     *
     * @param terminalCodeList
     */
    private void sendMessage(List<String> terminalCodeList, String customerCode) {
        //异步将所有绑定的终端对应的信息发送
        List<TRegist> list = tRegistService.list(new QueryWrapper<TRegist>().lambda().in(TRegist::getDeviceId, terminalCodeList));
        CompletableFuture.runAsync(() -> {
            list.forEach(tRegist -> {
                String mqContent = tRegist.getMqContent();
                Map<String, Object> map1 = JsonTool.jsonToMap(mqContent);
                Map map2 = (Map) map1.get("body");
                Map map3 = (Map) map2.get("header");
                map3.put("customerCode", customerCode);
                HttpRequest post = HttpUtil.createPost(MapServerConstant.REGIST_URL + JsonTool.beanToJson(map1));
                HttpResponse execute = post.execute();
                String result = execute.body();
                log.info("调用http://8.141.63.229:97/terminal/sendMessage，参数为：{}，返回信息：{}", tRegist.getMqContent(), result);
                if (!"success".equals(result)) {
                    throw new MapServerException(ResultErrorEnum.BMKPCM01);
                }
            });
        });
    }

    /**
     * 修改数据
     *
     * @param tOrderAddRequestDto 实体对象
     * @return 修改结果
     */
    @ApiOperation("修改订单信息")
    @PutMapping("/update")
    @Transactional(rollbackFor = Exception.class)
    public ApiResult update(@RequestBody TOrderAddRequestDto tOrderAddRequestDto) {
        log.info("---------updateOrder begin, tOrderAddRequestDto is {}----------", tOrderAddRequestDto);
        TOrder tOrder = BeanUtil.copyProperties(tOrderAddRequestDto, TOrder.class);
        //根据当前时间和购买周期计算到期时间
        LocalDateTime currentTime = tOrderAddRequestDto.getStartTime();
        if (!ObjectUtils.isEmpty(currentTime)) {
            Integer usePeriod = tOrderAddRequestDto.getUsePeriod();
            LocalDateTime expireTime = currentTime.plusMonths(usePeriod);
            tOrder.setExpireTime(expireTime);
        }
        int quantity = tOrderAddRequestDto.getTerminalCodeList().size();
        BigDecimal totalPaymentPrice = tOrderAddRequestDto.getPrice().multiply(new BigDecimal(tOrderAddRequestDto.getUsePeriod()))
                .multiply(new BigDecimal(quantity));
        tOrder.setQuantity(quantity);
        tOrder.setTotalPaymentPrice(totalPaymentPrice);
//        if (!CollectionUtils.isEmpty(tOrderAddRequestDto.getTerminalCodeList())) {
        //根据订单编码查询绑定的终端
        List<TTerminalStock> tTerminalStocks = tTerminalStockService.list(new QueryWrapper<TTerminalStock>().lambda().eq(TTerminalStock::getOrderCode, tOrderAddRequestDto.getOrderCode()));
        List<String> oldTerminalCodeList = tTerminalStocks.stream().map(TTerminalStock::getTerminalCode).collect(Collectors.toList());
        List<String> newTerminalCodeList = tOrderAddRequestDto.getTerminalCodeList();
        //本次要绑定的终端
        List<String> addTerminalCodeList = newTerminalCodeList.stream().filter(x -> !oldTerminalCodeList.contains(x)).collect(Collectors.toList());
        List<String> deleteTerminalCodeList = oldTerminalCodeList.stream().filter(x -> !newTerminalCodeList.contains(x)).collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(addTerminalCodeList)) {
            log.info("本次绑定的设备编码为：{}", addTerminalCodeList);
            UpdateWrapper<TTerminalStock> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().in(TTerminalStock::getTerminalCode, addTerminalCodeList)
                    .set(TTerminalStock::getOrderCode, tOrderAddRequestDto.getOrderCode())
                    .set(TTerminalStock::getDeliveryTime, LocalDateTime.now())
                    .set(TTerminalStock::getInventoryStatus, InventoryStatusEnum.ALLOCATED.getValue());
            tTerminalStockService.update(updateWrapper);

            updateFlowCardStockStatus(addTerminalCodeList);

            sendMessage(addTerminalCodeList, tOrder.getCustomerCode());
            //给协议方发送终端权限信息
            List<TServiceInfo> tServiceInfoList = tServiceInfoService.list(new QueryWrapper<TServiceInfo>().lambda()
                    .eq(TServiceInfo::getOrderCode, tOrderAddRequestDto.getOrderCode())
                    .eq(TServiceInfo::getStatus, ServiceStatusEnum.ENABLE.getValue())
                    .in(TServiceInfo::getServiceType, MapServerConstant.SERVICE_TYPE_LIST));
            Map<String, List<String>> map = tServiceInfoList.stream().collect(Collectors.groupingBy(TServiceInfo::getOrderCode, Collectors.mapping(TServiceInfo::getServiceType, Collectors.toList())));
            List<String> serviceTypeList = map.get(tOrderAddRequestDto.getOrderCode());
            List<TTerminalServiceMessageDto> tTerminalServiceMessageDtoList = addTerminalCodeList.stream().map(s -> {
                TTerminalServiceMessageDto tTerminalServiceMessageDto = new TTerminalServiceMessageDto();
                TTerminalInfo tTerminalInfo = tTerminalInfoService.getOne(new QueryWrapper<TTerminalInfo>().lambda().eq(TTerminalInfo::getTerminalCode, s));
                tTerminalServiceMessageDto.setFlowCardNumber(tTerminalInfo.getFlowCardNumber());
                if (CollectionUtils.isEmpty(serviceTypeList)) {
                    tTerminalServiceMessageDto.setAlarmAuth(false);
                    tTerminalServiceMessageDto.setLocationAuth(false);
                } else {
                    tTerminalServiceMessageDto.setLocationAuth(serviceTypeList.contains(MapServerConstant.LOCATION));
                    tTerminalServiceMessageDto.setAlarmAuth(serviceTypeList.contains(MapServerConstant.ALARM));
                }
                return tTerminalServiceMessageDto;
            }).collect(Collectors.toList());
            log.info("修改订单时新增设备推送权限为：{}", tTerminalServiceMessageDtoList);
            HttpUtils.sendAuthInfo(tTerminalServiceMessageDtoList);
        }
        if (!CollectionUtils.isEmpty(deleteTerminalCodeList)) {
            log.info("本次解绑的设备编码为：{}", deleteTerminalCodeList);
            UpdateWrapper<TTerminalStock> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().in(TTerminalStock::getTerminalCode, deleteTerminalCodeList)
                    .set(TTerminalStock::getOrderCode, "")
                    .set(TTerminalStock::getDeliveryTime, null)
                    .set(TTerminalStock::getInventoryStatus, InventoryStatusEnum.TOBEALLOCATED.getValue());
            tTerminalStockService.update(updateWrapper);

            cancelFlowCardStock(deleteTerminalCodeList);
            //调用取消接口
            cancelDevice(deleteTerminalCodeList, tOrder.getCustomerCode());

            //给协议方发送终端权限信息
            List<TTerminalServiceMessageDto> terminalServiceMessageDtoList = deleteTerminalCodeList.stream().map(s -> {
                TTerminalServiceMessageDto tTerminalServiceMessageDto = new TTerminalServiceMessageDto();
                TTerminalInfo tTerminalInfo = tTerminalInfoService.getOne(new QueryWrapper<TTerminalInfo>().lambda().eq(TTerminalInfo::getTerminalCode, s));
                tTerminalServiceMessageDto.setFlowCardNumber(tTerminalInfo.getFlowCardNumber());
                tTerminalServiceMessageDto.setAlarmAuth(false);
                tTerminalServiceMessageDto.setLocationAuth(false);
                return tTerminalServiceMessageDto;
            }).collect(Collectors.toList());
            log.info("修改订单时移除设备推送权限为：{}", terminalServiceMessageDtoList);
            HttpUtils.sendAuthInfo(terminalServiceMessageDtoList);
//            }
            //维护客户的已分配终端数量
            tCustomerInfoService.updateCustomerAssignedTerminalsNum(tOrderAddRequestDto.getCustomerCode(), addTerminalCodeList.size() - deleteTerminalCodeList.size());
            //给协议方发送终端权限信息
//            tTerminalStockService.sendTTerminalServiceMessageDto();
        }
        //维护客户的已分配终端数量
        tCustomerInfoService.updateCustomerAssignedTerminalsNum(tOrderAddRequestDto.getCustomerCode(), addTerminalCodeList.size() - deleteTerminalCodeList.size());
        return ApiResult.ok(this.tOrderService.updateById(tOrder));
    }

    /**
     * 将流量卡状态改为待出库
     *
     * @param deleteTerminalCodeList
     */
    private void cancelFlowCardStock(List<String> deleteTerminalCodeList) {
        log.info("修改设备对应的流量卡状态为待激活，参数为：{}", deleteTerminalCodeList);
        List<TTerminalInfo> tTerminalInfoList = tTerminalInfoService.list(new QueryWrapper<TTerminalInfo>().lambda().in(TTerminalInfo::getTerminalCode, deleteTerminalCodeList));
        if (CollectionUtils.isEmpty(tTerminalInfoList)) {
            return;
        }
        List<String> flowCardNumberList = tTerminalInfoList.stream().map(TTerminalInfo::getFlowCardNumber).collect(Collectors.toList());
        UpdateWrapper<TFlowCardStock> updateWrapper1 = new UpdateWrapper<>();
        updateWrapper1.lambda().in(TFlowCardStock::getFlowCardNumber, flowCardNumberList)
                .set(TFlowCardStock::getInventoryStatus, ActiveStatusEnum.TOBEALLOCATED.getValue())
                .set(TFlowCardStock::getDeliveryTime, null);
        tFlowCardStockService.update(updateWrapper1);
    }

    /**
     * 根据订单状态查询订单信息列表
     *
     * @return 所有数据
     */
    @ApiOperation("根据订单状态查询订单信息列表")
    @PostMapping("/selectOrderByPaymentStatus")
    public ApiResult<List<TOrderResponseDto>> selectOrderByPaymentStatus(@RequestParam("paymentStatus") Integer paymentStatus,
                                                                         @RequestParam("serviceType") String serviceType) {
        log.info("---------selectOrderByPaymentStatus begin");
        List<TOrder> orderList;
        QueryWrapper<TOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TOrder::getPaymentStatus, paymentStatus);
        List<TOrder> tOrderList = tOrderService.list(queryWrapper);
        if (StringUtils.isBlank(serviceType)) {
            orderList = tOrderList;
            List<TOrderResponseDto> tOrderResponseDtoList = BeanTool.copyObjListProperties(orderList, TOrderResponseDto.class);
            return ApiResult.ok(tOrderResponseDtoList);
        } else {
            List<TOrderResponseDto> tOrderResponseDtoList = tOrderList.stream().map(tOrder -> {
                TOrderResponseDto tOrderResponseDto = BeanUtil.copyProperties(tOrder, TOrderResponseDto.class);

                QueryWrapper<TServiceInfo> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.lambda().eq(TServiceInfo::getOrderCode, tOrder.getOrderCode()).eq(TServiceInfo::getServiceType, serviceType);
                List<TServiceInfo> list = tServiceInfoService.list(queryWrapper1);
                if (CollectionUtils.isEmpty(list)) {
                    tOrderResponseDto.setBindService(false);
                }
                return tOrderResponseDto;
            }).collect(Collectors.toList());
            return ApiResult.ok(tOrderResponseDtoList);
        }
//        List<TOrderResponseDto> tOrderResponseDtoList = BeanTool.copyObjListProperties(orderList, TOrderResponseDto.class);
//        log.info("---------selectOrderByPaymentStatus end, data is {}----------", tOrderResponseDtoList);
//        return ApiResult.ok(tOrderResponseDtoList);
    }

    /**
     * 作废订单
     *
     * @return
     */
    @ApiOperation("作废订单")
    @PostMapping("/abandonedOrder")
    public ApiResult abandonedOrder(@RequestParam("id") Integer id) {
        log.info("作废订单开始，id为：{}", id);
        TOrder tOrder = tOrderService.getById(id);
        if (ObjectUtils.isEmpty(tOrder)) {
            ApiResult.ok();
        }
        //给协议方发送终端权限信息
        abandoneOrderSendAuthInfo(Lists.newArrayList(tOrder.getOrderCode()));
        log.info("---------abandonedOrder begin");
        UpdateWrapper<TOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(TOrder::getId, id).set(TOrder::getPaymentStatus, OrderStatusEnum.OBSOLETE.getValue());
        tOrderService.update(updateWrapper);
        abandoneOrder(tOrder);

//        tTerminalStockService.sendTTerminalServiceMessageDto();
        log.info("---------abandonedOrder end");
        return ApiResult.ok();
    }

    /**
     * 作废订单
     *
     * @param tOrder
     */
    private void abandoneOrder(TOrder tOrder) {
        //更新客户绑定终端的个数
        log.info("abandoneOrder param is {}", tOrder);
        QueryWrapper<TTerminalStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TTerminalStock::getOrderCode, tOrder.getOrderCode());
        List<TTerminalStock> tTerminalStockList = tTerminalStockService.list(queryWrapper);
        tCustomerInfoService.updateCustomerAssignedTerminalsNum(tOrder.getCustomerCode(), -tTerminalStockList.size());

        //将库存中的订单和设备进行解绑 并清除出库时间 更改状态为 待出库
        UpdateWrapper<TTerminalStock> updateWrapper1 = new UpdateWrapper<>();
        updateWrapper1.lambda().eq(TTerminalStock::getOrderCode, tOrder.getOrderCode())
                .set(TTerminalStock::getDeliveryTime, null)
                .set(TTerminalStock::getInventoryStatus, InventoryStatusEnum.TOBEALLOCATED.getValue())
                .set(TTerminalStock::getOrderCode, "");
        tTerminalStockService.update(updateWrapper1);

        //修改流量卡信息
        List<String> terminalCodeList = tTerminalStockList.stream().map(TTerminalStock::getTerminalCode).collect(Collectors.toList());
        cancelFlowCardStock(terminalCodeList);
        //调用取消接口
        cancelDevice(terminalCodeList, tOrder.getCustomerCode());
    }

    /**
     * 取消设备
     *
     * @param terminalCodeList
     */
    private void cancelDevice(List<String> terminalCodeList, String customerCode) {
        //异步执行取消设备接口
        CompletableFuture.runAsync(() -> {
            terminalCodeList.forEach(terminalCode -> {
                TRegist tRegist = tRegistService.getOne(new QueryWrapper<TRegist>().lambda().eq(TRegist::getDeviceId, terminalCode));
                HttpRequest post = HttpUtil.createPost(MapServerConstant.CANCAL_DEVICE + terminalCode + "&mobileNo=" + tRegist.getMobileNo() + "&customerCode=" + customerCode);
                HttpResponse execute = post.execute();
                String result = execute.body();
                log.info("调用http://8.141.63.229:97/terminal/sendMessageClean，参数为：deviceId:{},mobileNo:{},customerCode:{}返回信息：{}", terminalCode, tRegist.getMobileNo(), customerCode, result);
                if (!"success".equals(result)) {
                    throw new MapServerException(ResultErrorEnum.BMKPCM02);
                }
            });
        });
    }


    @Scheduled(cron = "0 0 5 * * ? ")
//    @Scheduled(cron = "* * * * * ? ")
    @Transactional(rollbackFor = Exception.class)
    public void expireOrder() {
        //将订单变为作废状态
        List<TOrder> tOrderList = tOrderService.list(new QueryWrapper<TOrder>().lambda().lt(TOrder::getExpireTime, LocalDateTime.now()));
        if (!CollectionUtils.isEmpty(tOrderList)) {
            //推送设备权限信息
            List<String> orderCodeList = tOrderList.stream().map(TOrder::getOrderCode).collect(Collectors.toList());
            abandoneOrderSendAuthInfo(orderCodeList);
            tOrderService.update(new UpdateWrapper<TOrder>().lambda().in(TOrder::getOrderCode, orderCodeList).set(TOrder::getPaymentStatus, OrderStatusEnum.OBSOLETE.getValue()));
            tOrderList.forEach(tOrder -> abandoneOrder(tOrder));
        }
        //推送设备权限信息
//        tTerminalStockService.sendTTerminalServiceMessageDto();
    }

    /**
     * 作废发送权限信息
     *
     * @param orderCodeList
     */
    private void abandoneOrderSendAuthInfo(List<String> orderCodeList) {
        List<TTerminalServiceMessageDto> tTerminalServiceMessageDtoList = tTerminalStockDao.queryTerminalOrder(orderCodeList);
        tTerminalServiceMessageDtoList.forEach(tTerminalServiceMessageDto -> {
            tTerminalServiceMessageDto.setAlarmAuth(false);
            tTerminalServiceMessageDto.setLocationAuth(false);
        });
        log.info("订单过期作废推送权限数据，为：{}", tTerminalServiceMessageDtoList);
        HttpUtils.sendAuthInfo(tTerminalServiceMessageDtoList);
    }

    /**
     * 15、3、0天即将过期发送消息提醒
     */
    @Scheduled(cron = "0 0 5 * * ? ")
//    @Scheduled(cron = "* * * * * ? ")
    @Transactional(rollbackFor = Exception.class)
    public void sendMessageReminder() {
        orderRemindTimeList.forEach(s -> {
            List<TOrder> tOrderList = tOrderService.queryFifteenExpire();
            tOrderList.forEach(tOrder -> {
                TCustomerInfo tCustomerInfo = tCustomerInfoService.getOne(new QueryWrapper<TCustomerInfo>().lambda().eq(TCustomerInfo::getCustomerCode, tOrder.getCustomerCode()));
                //发送到期提醒
                if (ObjectUtil.isNotEmpty(tCustomerInfo) && StringUtils.isNotBlank(tCustomerInfo.getContactsPhone())) {
                    //转换到期时间
                    String expireTime = DateUtil.localDateTimeFormat(tOrder.getExpireTime(), "yyyyMMdd");
                    //短信提醒
                    aliSmsUtil.sendSms(tCustomerInfo.getContactsPhone(), expireTime);
                    //邮件提醒-您当前订单过期时间${remark},请及时处理
//                    String newEmailContent = emailContent.replace("{remark}", expireTime);
//                    emailUtil.sendMail("",emailSubject,newEmailContent);
                }
            });
        });
    }


    @Log("发送邮件")
    @PostMapping("/sendEmail")
    @ApiOperation("发送邮件")
    public ApiResult sendEmail(@Validated @RequestBody MyEmailDto myEmailDto) {
        MailAccount account = new MailAccount();
        account.setHost(myEmailDto.getHost());
        account.setPort(myEmailDto.getPort());
        account.setAuth(true);
        account.setFrom(myEmailDto.getFrom());
        account.setUser(myEmailDto.getUser());
        account.setPass(myEmailDto.getPass());
        MailUtil.send(account, myEmailDto.getToList(), myEmailDto.getSubject(), myEmailDto.getContent(), false);
        return ApiResult.ok();
    }
}
